<?php

namespace App\Http\Controllers\Admin;

use App\Exceptions\LessonPublishException;
use App\Models\AssistWord;
use App\Models\Attachment;
use App\Models\Knowledge;
use App\Models\Lesson;
use App\Models\LessonPage;
use App\Models\LessonSection;
use App\Models\LessonTest;
use App\Models\LessonTestLevel;
use App\Models\TestTemplate;

class LessonVersionController extends Controller
{
    private $wordCount = 0;
    private $essenceQaCount = 0;
    private $gameTestCount = 0;
    private $gameWordCount = 0;

    /*
     * @api put /course-api/a/lessons/{lessonId}/publish 发布课时
     * @version 0.0.1
     * @group admin
     *
     * @param path int lessonId 课时ID
     * @param body int status 状态：0不发布，1发布，2发布但有修改
     *
     * @response 200 正常结果 {
     *  "code":0,
     *  "msg":"",
     *  "data":{}
     * }
     */
    public function publish($lessonId)
    {
        $this->validate($this->request, [
            'status' => 'required|integer'
        ]);
        $status = $this->request->input('status');
        /** @var Lesson $lessonObj */
        $lessonObj = Lesson::find($lessonId);
        if ($status == 1) {
            try {
                $this->parseBookPage($lessonId);
            } catch (\Throwable $e) {
                throw new LessonPublishException('读绘本: ' . $e->getMessage());
            }
            try {
                $this->parseAnimationPage($lessonId);
            } catch (\Throwable $e) {
                throw new LessonPublishException('精读: ' . $e->getMessage());
            }
            try {
                $this->parseWords($lessonId);
            } catch (\Throwable $e) {
                throw new LessonPublishException('单词: ' . $e->getMessage());
            }
            try {
                $this->parseTests($lessonId);
            } catch (\Throwable $e) {
                throw new LessonPublishException('闯关: ' . $e->getMessage());
            }
            // 统计word count，knowledge count
            $lessonObj->setWordCount($this->wordCount);
            $lessonObj->setKnowledgeCount();
            $lessonObj->setGameTestCount($this->gameTestCount);
            $lessonObj->setEssenceQaCount($this->essenceQaCount);
            $lessonObj->setGameWordCount($this->gameWordCount);
        }
        $lessonObj->setPublished($status);
        $lessonObj->save();

        return $this->sendSuccessJson();
    }

    private function parseBookPage($lessonId)
    {
        $readSources = [];
        $followSources = [];
        $readPages = [];
        $followPages = [];
        /** @var Lesson $lessonObj */
        $lessonObj = Lesson::find($lessonId);

        $introduction = $lessonObj->getIntroduction();
        /** @var Attachment $attachmentObj */
        $attachmentObj = Attachment::find($introduction['attachmentId']);
        if (!$attachmentObj) {
            throw new \Exception("绘本附件信息为空");
        }

        try {
            $lessonAudio = $lessonObj->audio()->value('uri');
            $lessonCover = $lessonObj->cover()->value('uri');
            // @todo 处理图片
            $lessonCover = $lessonCover . '?x-oss-process=style/page';
            $readSources['audios'][] = $lessonAudio;
            $readSources['images'][] = $lessonCover;
            $readPages['cover'] = [
                'word_count' => $lessonObj->getWordCount(),
                'lexile' => $lessonObj->getLexile(),
                'audio' => $lessonAudio,
                'name' => $lessonObj->getName(),
                'cover' => $lessonCover
            ];
            if ($attachmentObj->getType() == 0) {
                $image = $attachmentObj->getUri();
                // @todo 处理图片
                $image = $image . '?x-oss-process=style/page';
                $readSources['images'][] = $image;
                $readPages['introduction']['image'] = $image;
            } elseif ($attachmentObj->getType() == 2) {
                $poster = '';
                if (!empty($introduction['coverImageId'])) {
                    $poster = Attachment::where('id', $introduction['coverImageId'])->value('uri');
                    // @todo 处理图片
                    $poster = $poster . '?x-oss-process=style/page';
                    $readSources['images'][] = $poster;
                }
                $video = $attachmentObj->getUri();
                $readPages['introduction']['video'] = [
                    'src' => $video,
                    'poster' => $poster
                ];
                $readSources['videos'][] = $video;
            }
            // 可以不配置文本
            $readPages['introduction']['sentences'] = [];
            if (!empty($introduction['sentences'])) {
                foreach ($introduction['sentences'] as $sentence) {
                    $item = ['text' => $sentence['sentence']];
                    if (!empty($sentence['audioId'])) {
                        $item['audio'] = Attachment::where('id', $sentence['audioId'])->value('uri');
                        $readSources['audios'][] = $item['audio'];
                    }
                    $readPages['introduction']['sentences'][] = $item;
                }
            }
        } catch (\Exception $e) {
            throw new \Exception("绘本导读错误, error {$e->getMessage()}");
        }

        $bookPages = LessonPage::where('lesson_id', $lessonId)->ofType(1)->get();

        /** @var LessonPage $pageObj */
        foreach ($bookPages as $pageObj) {
            try {
                $content = $pageObj->getContent();
                $bookSentences = [];
                $image = $content['attachment']['uri'];
                // @todo 处理图片
                $image = $image . '?x-oss-process=style/page';
                foreach ($content['sentences'] as $sentence) {
                    $origSentence = str_replace('-', ' ', $sentence['sentence']);
                    $this->wordCount += str_word_count($origSentence);
                    $sentenceWords = [];
                    $followWords = [];
                    foreach ($sentence['words'] as $word) {
                        $word['explain'] = null;
                        if (!empty($word['knowledgeId'])) {
                            /** @var Knowledge $knowledge */
                            $knowledge = Knowledge::find($word['knowledgeId']);
                            $word['explain'] = [
                                'type' => $word['type'],
                                'audio' => $knowledge->audio()->value('uri'),
                                'image' => null,
                                'chinese' => null,
                            ];
                            if ($word['type'] == 1) {
                                $word['explain']['chinese'] = $knowledge->getChinese();
                            } else {
                                $word['explain']['image'] = $knowledge->getCover();
                                $readSources['images'][] = $knowledge->getCover();
                            }
                        } elseif (!empty($word['assistId'])) {
                            /** @var AssistWord $assistWordObj */
                            $assistWordObj = AssistWord::find($word['assistId']);
                            $word['explain'] = [
                                'type' => $word['type'],
                                'audio' => $assistWordObj->audio()->value('uri'),
                                'image' => null,
                                'chinese' => null,
                            ];
                            if ($word['type'] == 1) {
                                $word['explain']['chinese'] = $assistWordObj->getChinese();
                            } else {
                                $cover =  $assistWordObj->cover()->value('uri');
                                if ($cover) {
                                    $cover = $cover . '?x-oss-process=style/word';
                                    $word['explain']['image'] = $cover;
                                    $readSources['images'][] = $cover;
                                }
                            }
                        }
                        unset($word['type']); // 单词解释类型：1, 文本；2，图片
                        $sentenceWords[] = $word;

                        unset($word['knowledgeId']);
                        unset($word['assistId']);
                        unset($word['explain']);
                        // 跟读
                        $followWords[] = $word;
                    }
                    $bookSentences[] = [
                        'audio' => $sentence['audio']['uri'],
                        'words' => $sentenceWords
                    ];
                    $readSources['audios'][] = $sentence['audio']['uri'];
                    if (!empty($sentence['isFollowed'])) {
                        $followPages[] = [
                            'pageId' => $pageObj->getId(),
                            'image' => $image,
                            'sentence' => $origSentence,
                            'audio' => $sentence['audio']['uri'],
                            'words' => $followWords
                        ];
                    }
                }

                $readSources['images'][] = $image;
                $readPages['pages'][] = [
                    'image' => $image,
                    'sentences' => $bookSentences
                ];
            } catch (\Exception $e) {
                throw new \Exception("绘本内容: name {$pageObj->getName()}, error {$e->getMessage()}");
            }
        }
        if (!$readPages) {
            throw new \Exception("绘本内容为空");
        }
        if (!$followPages) {
            throw new \Exception("绘本跟读内容为空");
        }
        LessonSection::updateOrCreate(['lesson_id'=>$lessonId, 'section'=>LessonSection::SECTION['read']], ['metadata'=>json_encode($readPages), 'sources'=>json_encode($readSources)]);
        LessonSection::updateOrCreate(['lesson_id'=>$lessonId, 'section'=>LessonSection::SECTION['dub']], ['metadata'=>json_encode($followPages), 'sources'=>json_encode($followSources)]);
    }


    private function parseAnimationPage($lessonId)
    {
        $animations = [];
        $sources = [];
        $animationPages = LessonPage::where('lesson_id', $lessonId)->ofType(2)->get();
        /** @var LessonPage $pageObj */
        foreach ($animationPages as $pageObj) {
            try {
                $content = $pageObj->getContent();
                $sentences = [];
                foreach ($content['sentences'] as $sentence) {
                    $image = $sentence['image']['uri'] ?? null;
                    $audio = $sentence['audio']['uri'] ?? null;
                    // @todo 处理图片
                    if ($image) {
                        $image = $image . '?x-oss-process=style/anim_page';
                    }
                    $image && $sources['images'][] = $image;
                    $audio && $sources['audios'][] = $audio;
                    if ($sentence['type'] === 'answer') {
                        $this->essenceQaCount++;
                    }
                    $sentences[] = [
                        'type' => $sentence['type'],
                        'image' => $image,
                        'sentence' => !empty($sentence['sentence']) ? explode("\n", $sentence['sentence']) : null,
                        'audio' => $audio,
                        'imageId' => $sentence['relatedImageId'] ?? null
                    ];
                }
                $images = [];
                foreach ($content['images'] as $image) {
                    // @todo 处理图片
                    $image['url'] = $image['url'] . '?x-oss-process=style/anim_page';
                    $sources['images'][] = $image['url'];
                    $images[] = [
                        'id' => $image['id'],
                        'top' => $image['top'],
                        'left' => $image['left'],
                        'width' => $image['width'],
                        'height' => $image['height'],
                        'animation' => $image['anim'] ?? null,
                        'image' => $image['url']
                    ];
                }
                $animations[] = [
                    'sentences' => $sentences,
                    'images' => $images
                ];
            } catch (\Exception $e) {
                throw new \Exception("name {$pageObj->getName()}, error {$e->getMessage()}");
            }
        }
        if (!$animations) {
            throw new \Exception("绘本精读内容为空");
        }
        LessonSection::updateOrCreate(['lesson_id'=>$lessonId, 'section'=>LessonSection::SECTION['essence']], ['metadata'=>json_encode($animations), 'sources'=>json_encode($sources)]);
    }

    private function parseWords($lessonId)
    {
        $knowledge = Lesson::find($lessonId)->knowledge()->get();
        $knowledgePages = [];
        $sources = [
            'images' => []
        ];
        /** @var Knowledge $knowledgeObj */
        foreach ($knowledge as $knowledgeObj) {
            try {
                $audio = $knowledgeObj->audio()->value('uri');
                $images = $knowledgeObj->getImagesForTest();
                $sources['audios'][] = $audio;
                $sources['images'] = array_merge($sources['images'], $images);
                $knowledgePages[] = [
                    'images' => $images,
                    'name' => $knowledgeObj->getName(),
                    'chinese' => $knowledgeObj->getChinese(),
                    'knowledgeId' => $knowledgeObj->getId(),
                    'tagId' => $knowledgeObj->tag()->value('id'),
                    'audio' => $audio
                ];
            } catch (\Exception $e) {
                throw new \Exception("name {$knowledgeObj->getName()}, error {$e->getMessage()}");
            }
        }
        if (!$knowledgePages) {
            throw new \Exception("绘本单词内容为空");
        }
        LessonSection::updateOrCreate(['lesson_id'=>$lessonId, 'section'=>LessonSection::SECTION['word']], ['metadata'=>json_encode($knowledgePages), 'sources'=>json_encode($sources)]);
    }

    private function parseTests($lessonId)
    {
        $testKnowledge = [];
        $testPages = [];
        $sources = [
            'images' => []
        ];
        $tests = LessonTest::where('lesson_id', $lessonId)->orderBy('sequence', 'asc')->orderBy('id', 'desc')->get();
        $this->gameTestCount = LessonTest::where('lesson_id', $lessonId)->count();
        /** @var LessonTest $testObj */
        foreach ($tests as $testObj) {
            $templateName = TestTemplate::where('id', $testObj->getTemplateId())->value('name');
            $level = LessonTestLevel::where('id', $testObj->getLevelId())->value('level');
            $content = $testObj->getContent();
            $knowledgeObj = null;
            if (!empty($content['knowledgeId'])) {
                /** @var Knowledge $knowledgeObj */
                $knowledgeObj = Knowledge::find($content['knowledgeId']);
                $testKnowledge[$content['knowledgeId']] = '';
            } else {
                $this->gameWordCount = count($content['answer']);
            }
            if (empty($testPages[$level])) {
                $testPages[$level] = [
                    'level' => $level
                ];
            }
            $test = [];
            try {
                switch ($templateName) {
                    case 'template1':
                        $audio = $knowledgeObj->audio()->value('uri');
                        $cover = $knowledgeObj->getCover();
                        $sources['audios'][] = $audio;
                        $sources['images'][] = $cover;
                        $test = [
                            'type' => 'template1',
                            'time' => $content['timer'],
                            'content' => [
                                'knowledgeId' => $knowledgeObj->getId(),
                                'tagId' => $knowledgeObj->tag()->value('id'),
                                'name' => $knowledgeObj->getName(),
                                'chinese' => $knowledgeObj->getChinese(),
                                'image' => $cover,
                                'audio' => $audio,
                                'answer' => [$knowledgeObj->getChinese()],
                                'options' => array_merge($content['options'], [$knowledgeObj->getChinese()])
                            ],
                        ];
                        break;
                    case 'template2':
                        $audio = $knowledgeObj->audio()->value('uri');
                        $sources['audios'][] = $audio;
                        $test = [
                            'type' => 'template2',
                            'time' => $content['timer'],
                            'content' => [
                                'knowledgeId' => $knowledgeObj->getId(),
                                'tagId' => $knowledgeObj->tag()->value('id'),
                                'name' => $knowledgeObj->getName(),
                                'chinese' => $knowledgeObj->getChinese(),
                                'audio' => $audio,
                                'answer' => [$knowledgeObj->getChinese()],
                                'options' => array_merge($content['options'], [$knowledgeObj->getChinese()])
                            ],
                        ];
                        break;
                    case 'template3':
                        $audio = $knowledgeObj->audio()->value('uri');
                        $sources['audios'][] = $audio;
                        $test = [
                            'type' => 'template3',
                            'time' => $content['timer'],
                            'content' => [
                                'knowledgeId' => $knowledgeObj->getId(),
                                'tagId' => $knowledgeObj->tag()->value('id'),
                                'name' => $knowledgeObj->getName(),
                                'chinese' => $knowledgeObj->getChinese(),
                                'image' => $knowledgeObj->getCover(),
                                'audio' => $audio,
                                'answer' => $content['answer'],
                                'options' => array_merge($content['options'], $content['answer'])
                            ],
                        ];
                        break;
                    case 'template4':
                        $audio = $knowledgeObj->audio()->value('uri');
                        $sources['audios'][] = $audio;
                        $optionsImgs = [];
                        foreach ($content['options'] as $image) {
                            // @todo 处理图片
                            $image['uri'] = $image['uri'] . '?x-oss-process=style/word';
                            $optionsImgs[] = $image['uri'];
                        }
                        $test = [
                            'type' => 'template4',
                            'time' => $content['timer'],
                            'content' => [
                                'knowledgeId' => $knowledgeObj->getId(),
                                'tagId' => $knowledgeObj->tag()->value('id'),
                                'name' => $knowledgeObj->getName(),
                                'chinese' => $knowledgeObj->getChinese(),
                                'audio' => $audio,
                                'answer' => [$knowledgeObj->getCover()],
                                'options' => array_merge($optionsImgs, [$knowledgeObj->getCover()])
                            ],
                        ];
                        $sources['images'] = array_merge($sources['images'], $test['content']['options']);
                        break;
                    case 'template5':
                        $audio = $knowledgeObj->audio()->value('uri');
                        $sources['audios'][] = $audio;
                        $test = [
                            'type' => 'template5',
                            'time' => $content['timer'],
                            'content' => [
                                'knowledgeId' => $knowledgeObj->getId(),
                                'tagId' => $knowledgeObj->tag()->value('id'),
                                'name' => $knowledgeObj->getName(),
                                'chinese' => $knowledgeObj->getChinese(),
                                'audio' => $audio,
                                'answer' => $content['answer'],
                                'options' => array_merge($content['options'], $content['answer'])
                            ],
                        ];
                        break;
                    case 'template6':
                        $audio = $knowledgeObj->audio()->value('uri');
                        $sources['audios'][] = $audio;
                        $optionsImgs = [];
                        foreach ($content['options'] as $image) {
                            // @todo 处理图片
                            $image['uri'] = $image['uri'] . '?x-oss-process=style/word';
                            $optionsImgs[] = $image['uri'];
                        }
                        $answers = $knowledgeObj->getImagesForTest(2);
                        $test = [
                            'type' => 'template6',
                            'time' => $content['timer'],
                            'content' => [
                                'knowledgeId' => $knowledgeObj->getId(),
                                'tagId' => $knowledgeObj->tag()->value('id'),
                                'name' => $knowledgeObj->getName(),
                                'chinese' => $knowledgeObj->getChinese(),
                                'audio' => $audio,
                                'answer' => $answers,
                                'options' => array_merge($optionsImgs, $answers)
                            ],
                        ];
                        $sources['images'] = array_merge($sources['images'], $test['content']['options']);
                        break;
                    case 'template7':
                        $image = $content['image']['uri'];
                        $audio = $content['audio']['uri'];
                        // @todo 处理图片
                        $image = $image . '?x-oss-process=style/word';
                        $sources['images'][] = $image;
                        $sources['audios'][] = $audio;
                        $test = [
                            'type' => 'template7',
                            'time' => $content['timer'],
                            'content' => [
                                'audio' => $audio,
                                'image' => $image,
                                'sentence' => $content['sentence'],
                                'answer' => $content['answer'],
                                'options' => array_merge($content['answer'], $content['options'])
                            ],
                        ];
                        break;
                }
            } catch (\Exception $e) {
                throw new \Exception("level: {$level}, name: {$testObj->getName()}, error {$e->getMessage()}");
            }
            $testPages[$level]['tests'][] = $test;
        }
        $this->gameWordCount += count($testKnowledge);
        if (!$testPages) {
            throw new \Exception("绘本闯关内容为空");
        }
        ksort($testPages);
        LessonSection::updateOrCreate(['lesson_id'=>$lessonId, 'section'=>LessonSection::SECTION['game']], ['metadata'=>json_encode(array_values($testPages)), 'sources'=>json_encode($sources)]);
    }
}
